package com.wz.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;

public class DiscardServer {
	private int port;

	public DiscardServer(int port){
		this.port = port;
	}

	public void run() throws Exception{
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try{
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
				ChannelInboundHandlerAdapter adapter = null;
				AttributeKey<Integer> key = AttributeKey.valueOf("test");
				@Override
				public void channelActive(ChannelHandlerContext ctx) throws Exception {
					System.out.println("channelActive");
					super.channelActive(ctx);
				}

				@Override
				public void channelInactive(ChannelHandlerContext ctx) throws Exception {
					System.out.println("channelInactive");
					super.channelInactive(ctx);
				}

				@Override
				public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
					System.out.println("channelRead");
					super.channelRead(ctx, msg);
				}

				@Override
				public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
					System.out.println("exceptionCaught");
					super.exceptionCaught(ctx, cause);
				}

				@Override
				public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
					System.out.println("channelReadComplete");
					super.channelReadComplete(ctx);
				}

				@Override
				public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
					System.out.println("channelUnregistered");
					super.channelUnregistered(ctx);
				}

				@Override
				public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
					System.out.println("channelWritabilityChanged");
					super.channelWritabilityChanged(ctx);
				}

				@Override
				public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
					System.out.println("userEventTriggered");
					super.userEventTriggered(ctx, evt);
				}
				
				@Override
				public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
					Attribute<Integer> attr = ctx.attr(key);
					if (attr.get() == null){
						attr.set(1);
					}
					attr.set(attr.get()+1);
					System.out.println("handlerAdded" + attr.get());
					super.handlerAdded(ctx);
				}

				@Override
				public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
					System.out.println("handlerRemoved");
					super.handlerRemoved(ctx);
				}

				@Override
				public boolean isSharable() {
					System.out.println(super.isSharable());
					return super.isSharable();
//					return false;
				}

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					if (adapter == null){
						adapter = new DiscardServerHandler();
					}
					System.out.println("initChannel");
					ch.pipeline().addLast(new ClientWriteHandler());
					ch.pipeline().addLast(adapter);
				}
			}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);
			ChannelFuture f = b.bind(port).sync();
			f.channel().closeFuture().sync();
		} finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
	}

	public static void main(String[] args) {
		DiscardServer ds = new DiscardServer(8001);
		try {
			ds.run();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}